
#include <Unit.h>
#include <ostream>
#include <LengthUnit.h>
#include <algorithm>
#include <Formatter.h>

namespace{
bool greaterThan(const Unit * lhs, const Unit * rhs)
{
	return *lhs > *rhs;
}
}

std::ostream& operator<<(std::ostream& out, const Unit& unit)
{
	out << unit.name_m;
	return out;
}


Unit::Unit(int factor, string name, const eUnitType unitType)
	:factor_m(factor), name_m(name), unitType_m(unitType)
{
}

const Unit& Unit::getInvalidUnit()
{
	static const Unit invalidUnit(0, "INVALID_TYPE", E_INVALID_TYPE);
	return invalidUnit;
}

bool Unit::hasSameUnitType(const Unit & unit) const 
{
	return unitType_m == unit.unitType_m;
}

int Unit::convertToNormalizedAmount(int length) const
{
	return factor_m * length;
}


bool Unit::operator > (const Unit & unit) const
{
	return factor_m > unit.factor_m;
}

void Unit::getFloorUnitStream(std::ostream& out, int amountInBaseUnit, bool& firstUnitFound) const
{
	if(amountInBaseUnit/factor_m > 0)
	{
		if(firstUnitFound)   	out << " " ;
		out << amountInBaseUnit/factor_m << " " << name_m;
		firstUnitFound = true;
	}
}

int Unit::getRestAmountInBaseUnit(int amountInBaseUnit) const
{
	return amountInBaseUnit%factor_m;
}

void Unit::printBaseUnitList(const Formatter& formatter)const
{
	OrderedUnits orderedUnits;
	appendAndSortUnit(orderedUnits, getBaseUnit());
	
	for_each(orderedUnits.begin(), orderedUnits.end(), formatter);
}

void Unit::appendAndSortUnit(OrderedUnits & orderedunits, const Unit & unit) const
{
	orderedunits.push_back(&unit);
	std::sort(orderedunits.begin(), orderedunits.end(), greaterThan);
}

